package model.components.networks.factory;

import java.util.ArrayList;
import java.util.List;

import model.components.links.factory.VirtualLinksFactory;
import model.components.links.link.Link;
import model.components.networks.network.VirtualNetwork;
import model.components.nodes.factory.VirtualNodesFactory;
import model.components.nodes.node.Node;

import cern.jet.random.Exponential;
import cern.jet.random.Poisson;
import cern.jet.random.engine.DRand;
import edu.uci.ics.jung.graph.Graph;

public class VirtualNetworksFactory extends NetworksFactory
{
	public static final String NAME_PREFIX = "VirtualNetwork";
	public static final int NETWORKS_NUMBER = 10;
			
	public static final int MIN_NODES_NUMBER = 2;
	public static final int MAX_NODES_NUMBER = 2;
	
	public static final String LINKS_NUMBER_TYPE = NetworksFactory.PERCENTAGE;
	public static final int LINKS_NUMBER_PERCENTAGE = 25;
	public static final int MIN_LINKS_NUMBER_RANGE =  1;
	public static final int MAX_LINKS_NUMBER_RANGE = 10;
	
	public static final int WINDOW_TIME_UNITS_NUMBER = 1;
	public static final double POISSON_ARRIVES = 1;
	public static final double EXPONENTIAL_LIFETIME = 10;
	
	private List< VirtualNetwork > virtualNetworks;
	public List< VirtualNetwork > getVirtualNetworks(){ return virtualNetworks; }
	public void setVirtualNetworks( List< VirtualNetwork > virtualNetworks ){ this.virtualNetworks = virtualNetworks; }

	public VirtualNetworksFactory()
	{
		Poisson poisson = new Poisson( POISSON_ARRIVES, new DRand() );
		Exponential exponential = new Exponential( 1 / EXPONENTIAL_LIFETIME, new DRand() );
		
		int networknumber = 0;
		int startingDate = 0;
		
		this.setVirtualNetworks( new ArrayList< VirtualNetwork >() );
		
		List< VirtualNetwork > virtualNetworks = new ArrayList< VirtualNetwork >();
		
		while( networknumber < NETWORKS_NUMBER )
		{
			int virtualNetworkRequestsNumber = poisson.nextInt();
			
			for( int j = 0; j < virtualNetworkRequestsNumber; j++ )
				if( networknumber < NETWORKS_NUMBER )
				{
					int endingDate = startingDate + exponential.nextInt();
					VirtualNodesFactory virtualNodesFactory = new VirtualNodesFactory( NAME_PREFIX + networknumber, startingDate, endingDate );
					VirtualLinksFactory virtualLinksFactory = new VirtualLinksFactory( NAME_PREFIX + networknumber, startingDate, endingDate );
					
					Graph< Node, Link > graph = null;
					
					if( LINKS_NUMBER_TYPE.equals( PERCENTAGE ) )
						graph = this.getErdosRenyiGraph( virtualNodesFactory, virtualLinksFactory, MIN_NODES_NUMBER, MAX_NODES_NUMBER, LINKS_NUMBER_PERCENTAGE );
					
					else if( LINKS_NUMBER_TYPE.equals( RANGE ) )
						graph = this.getBarabasiAlbertGraph( virtualNodesFactory, virtualLinksFactory, MIN_NODES_NUMBER, MAX_NODES_NUMBER, MIN_LINKS_NUMBER_RANGE, MAX_LINKS_NUMBER_RANGE );
					
					virtualNetworks.add( new VirtualNetwork( NAME_PREFIX, networknumber++, graph, startingDate, endingDate ) );
				}
			
			startingDate += WINDOW_TIME_UNITS_NUMBER;
		}
		
		this.setVirtualNetworks( virtualNetworks );
	}

	public VirtualNetworksFactory( String namePrefix, int networksNumber, int windowTimeUnitsNumber, double poissonArrives, double exponentialLifetime, int minNodesNumber, int maxNodesNumber, int routersPercentage, int switchesPercentage, int serversPercentage, int linuxPercentage, int windowsPercentage, int solarisPercentage, int androidPercentage, int vmWarePercentage, int xenPercentage, int kvmPercentage, int umlPercentage, int minCpu, int maxCpu, int minMemory, int maxMemory, int minDiskSpace, int maxDiskSpace, int linksNumberPercentage, int vlanPercentage, int sonetPercentage, int eight0211Percentage, int minBandwidth, int maxBandwidth )
	{
		Poisson poisson = new Poisson( poissonArrives, new DRand() );
		Exponential exponential = new Exponential( 1 / exponentialLifetime, new DRand() );
		
		int networknumber = 0;
		int startingDate = 0;
		
		this.setVirtualNetworks( new ArrayList< VirtualNetwork >() );
		
		List< VirtualNetwork > virtualNetworks = new ArrayList< VirtualNetwork >();
		
		while( networknumber < networksNumber )
		{
			int virtualNetworkRequestsNumber = poisson.nextInt();
			
			for( int j = 0; j < virtualNetworkRequestsNumber; j++ )
				if( networknumber < networksNumber )
				{
					int endingDate = startingDate + exponential.nextInt();
					VirtualNodesFactory virtualNodesFactory = new VirtualNodesFactory( namePrefix + networknumber, startingDate, endingDate );
					VirtualLinksFactory virtualLinksFactory = new VirtualLinksFactory( namePrefix + networknumber, startingDate, endingDate );
					
					Graph< Node, Link > graph = this.getErdosRenyiGraph( virtualNodesFactory, virtualLinksFactory, minNodesNumber, maxNodesNumber, linksNumberPercentage );
					
					virtualNetworks.add( new VirtualNetwork( NAME_PREFIX, networknumber++, graph, startingDate, startingDate + exponential.nextInt() ) );
				}
			
			startingDate += WINDOW_TIME_UNITS_NUMBER;
		}
		
		this.setVirtualNetworks( virtualNetworks );
	}
	
	public VirtualNetworksFactory( String namePrefix, int networksNumber, int windowTimeUnitsNumber, double poissonArrives, double exponentialLifetime, int minNodesNumber, int maxNodesNumber, int routersPercentage, int switchesPercentage, int serversPercentage, int linuxPercentage, int windowsPercentage, int solarisPercentage, int androidPercentage, int vmWarePercentage, int xenPercentage, int kvmPercentage, int umlPercentage, int minCpu, int maxCpu, int minMemory, int maxMemory, int minDiskSpace, int maxDiskSpace, int minLinksNumber, int maxLinksNumber, int vlanPercentage, int sonetPercentage, int eight0211Percentage, int minBandwidth, int maxBandwidth )
	{
		Poisson poisson = new Poisson( poissonArrives, new DRand() );
		Exponential exponential = new Exponential( 1 / exponentialLifetime, new DRand() );
		
		int networknumber = 0;
		int startingDate = 0;
		
		this.setVirtualNetworks( new ArrayList< VirtualNetwork >() );
		
		List< VirtualNetwork > virtualNetworks = new ArrayList< VirtualNetwork >();
		
		while( networknumber < networksNumber )
		{
			int virtualNetworkRequestsNumber = poisson.nextInt();
			
			for( int j = 0; j < virtualNetworkRequestsNumber; j++ )
				if( networknumber < networksNumber )
				{
					int endingDate = startingDate + exponential.nextInt();
					VirtualNodesFactory virtualNodesFactory = new VirtualNodesFactory( namePrefix + networknumber, startingDate, endingDate, routersPercentage, switchesPercentage, serversPercentage, linuxPercentage, windowsPercentage, solarisPercentage, androidPercentage, vmWarePercentage, xenPercentage, kvmPercentage, umlPercentage, minCpu, maxCpu, minMemory, maxMemory, minDiskSpace, maxDiskSpace );
					VirtualLinksFactory virtualLinksFactory = new VirtualLinksFactory( namePrefix + networknumber, startingDate, endingDate, minBandwidth, maxBandwidth, vlanPercentage, sonetPercentage, eight0211Percentage );
					Graph< Node, Link > graph = this.getBarabasiAlbertGraph( virtualNodesFactory, virtualLinksFactory, minNodesNumber, maxNodesNumber, minLinksNumber, maxLinksNumber);
					
					virtualNetworks.add( new VirtualNetwork( NAME_PREFIX, networknumber++, graph, startingDate, startingDate + exponential.nextInt() ) );
				}
			
			startingDate += WINDOW_TIME_UNITS_NUMBER;
		}
		
		this.setVirtualNetworks( virtualNetworks );
	}

}
